package admin.models;

import helpers.GeneralHelper;
import helpers.IdUniqueHelper;

import java.util.ArrayList;
import java.util.List;

import javax.cache.Cache;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;

import entities.Category;
import entities.Link;

public class LinkModel {
	
	private Objectify ofy;

	private Cache cache = null;

	private String cachePrefix = "link_";

	private static LinkModel instance = null;
	
	public static LinkModel getInstance() {
		if (instance == null) {
			instance = new LinkModel();
		}
		
		return instance;
	}
	
	private LinkModel() {
		try {
			ObjectifyService.register(Link.class);
		} catch (Exception e) {
			// e.printStackTrace();
		}
		cache = GeneralHelper.getCache();
		ofy = GeneralHelper.getObjectify();
	}

	public List<Link> list(int limit, int page) {
		List<Link> links = new ArrayList<Link>();

		int start = (page - 1) * limit;
		try {
			links = ofy.query(Link.class).limit(limit).offset(start).list();
		} catch (Exception e) {
			links = null;
		}
		
		if (links == null) {
			links = new ArrayList<Link>();
		}
		
		return links;
	}
	
	public List<Link> listByCategory(String cId, int limit, int page) {
		List<Link> links = new ArrayList<Link>();
		
		int start = (page - 1) * limit;
		try {
			links = ofy.query(Link.class).filter("category", cId).limit(limit).offset(start).list();
		} catch (Exception e) {
			links = null;
		}
		
		if (links == null) {
			links = new ArrayList<Link>();
		}
		
		return links;
	}
	
	public void insert(Link link) {
		boolean isNew = true;
		if (link.getId() != null) {
			isNew = false;
		} else {
			link.setId(IdUniqueHelper.getId());
		}
		
		ofy.put(link);
		
		//update count category
		CategoryModel categoryModel = CategoryModel.getInstance();
		Category category = categoryModel.getCategory(link.getCategory());
		
		if (category != null && isNew && link.getStatus() == 2) {
			updateCount(category, 1);
		}

		if (!isNew && !link.getLastCategory().isEmpty() && !link.getLastCategory().equals(link.getCategory()) && link.getStatus() == 2) {
			//+1 to count with new category
			if (category != null) {
				updateCount(category, 1);
			}
			//-1 to count with old category
			category = categoryModel.getCategory(link.getLastCategory());
			if (category != null) {
				updateCount(category, -1);
			}
		}
	}
	
	private void updateCount(Category category, int num) {
		CategoryModel categoryModel = CategoryModel.getInstance();
		int count = 0;
		String[] parents = category.getParents().split(",");
		for (int i = 0 ; i < parents.length; i++) {
			category = categoryModel.getCategory(parents[i]);
			if (category != null) {
				count = category.getCount() + num;
				if (count < 0) count = 0;
				category.setCount(count);
				categoryModel.update(category);
			}
		}
	}
	
	public Link get(String id) {
		Link link = new Link();
		
		try {
			link = ofy.get(new Key<Link>(Link.class, id));
		} catch (Exception e) {
			link = null;
		}
		
		return link;
	}
	
	public void delete(Link link) {
		//-1 to count with category
		if (link.getStatus() == 2) {
			CategoryModel categoryModel = CategoryModel.getInstance();
			Category category = categoryModel.getCategory(link.getCategory());
			if (category != null) {
				updateCount(category, -1);
			}
		}
		ofy.delete(link);
	}
	
	public boolean hasLinkInDirectory(String cid) {
		boolean exists = false;
		
		Link link = null;
		try {
			link = ofy.query(Link.class).filter("category", cid).get();
		} catch (Exception e) {
			// TODO: handle exception
		}
		
		
		if(link != null) {
			exists = true;
		}
		
		return exists;
	}
	
	public void update(Link link) {
		ofy.put(link);
	}
	
	public Link updateStatus(Link link, int status) {
		if (link != null && link.getStatus() != status) {
			CategoryModel categoryModel = CategoryModel.getInstance();
			Category category = categoryModel.getCategory(link.getCategory());
			if (category != null) {
				if (status == 2) {
					updateCount(category, 1);
				} else if (link.getStatus() == 2) {
					updateCount(category, -1);
				}
			}
			
			link.setStatus(status);
			update(link);
			
		}
		return link;
	}
}
